import {onMounted, onUnmounted} from 'vue';
import loopControl from "./loopControl";
import FormBase from "../../../components/js/FormBase";
import Dialog from "@/js/Dialog";
import Util from "@/js/Util.js";
import Request from '@/js_sdk/index.js'
import formula from "./formula";
import {FormApi} from "@/api/FormApi.js";
import FormValidate from "./FormValidate.js"
import TokenUtil from "../../../../../common/TokenUtil";

const rxAjax = new Request();

export default {
    mixins: [FormBase,formula,FormValidate],
    data() {
        return {
            //提交时是否校验必填
            checkRequired: true,
            //判断是是移动false还是pc：true
            isPcMode:false
        }
    },
    created() {
        if (this.createdShow) {
            return
        }
        //触发公共js事件
        const listener = (btn, curRow) => {
            if (curRow) {
                this[curRow](btn);
            }
        };
        onMounted(() => {
            this.$eventBus.$on('triggerEmitEvents', listener);
            this.$eventBus.$on('handlePublicEvent', this.handlePublicEventJs);
        });
        onUnmounted(() => {
            //删除dmo方法
            this.$eventBus.$off('triggerEmitEvents', listener);
            this.$eventBus.$off('handlePublicEvent', this.handlePublicEventJs);
        });
    },
    methods: {
        /**
         * 控件触发公共事件 处理公式、自定义查询
         * @param event 触发事件类型
         * @param value 字段值
         * @param key 字段标识
         * @param entName 表名 主表为main
         * @param data 表单数据
         */
        handlePublicEventJs(event, val, metadataItem){
            //一对多和一对一不触发
            if(['subTable','oneTable'].includes(metadataItem.type)){
                return;
            }
            let entName = metadataItem.subTable?metadataItem.subTable:'main';
            this.handlePublicEvent(event, val[0], metadataItem.field, entName, val[1])
        },
        //栅格布局
        gridRules(item) {
            let result = {success: true, msg: '校验通过'}
            let latent = this.showControl(item)//显示
            if (latent) {
                for (const res of item.children) {
                    let show = true
                    if(res.colCondition && res.colCondition.condition){
                        show = this.showConfig(res.colCondition)
                    }
                    if(show){
                        for (const res_ of res.children) {
                            let fn = this.forRules(res_);
                            if (fn && !fn.success) {
                                return fn
                            }
                        }
                    }
                }
            }
            return result
        },

        //子表
        subTableRules(item) {
            for (let rulesItem of item.rules) {
                let fn = this.reqMsg(rulesItem, item, this.data['sub__' + item.field].length, this.$i18(item.name), this.data['sub__' + item.field])
                if (fn && !fn.success) {
                    return fn
                    break
                }
            }
            //子表里面控件判断
            for (let obj of this.data['sub__' + item.field]) {
                let children = this.itemChildren(item.children)
                for (let objChildren of children) {
                    if (this.subShowControl(objChildren)) {
                        let name = this.$i18(item.name) + "[" + this.$i18(objChildren.controlConfig.name) + "]"
                        for (let rulesItem of objChildren.controlConfig.rules) {
                            let fn = this.reqMsg(rulesItem, objChildren.controlConfig, obj[objChildren.controlConfig.field], name, this.permission.subTable[item.field].fields[objChildren.field], obj)
                            if (fn && !fn.success) {
                                return fn
                                break
                            }
                        }
                        if (this.permission.subTable[item.field].fields[objChildren.field] == 'required' && !obj[objChildren.controlConfig.field]) {
                            return {success: false, msg: name + '必填'};
                            break
                        }
                    }
                }
            }
            return {success: true, msg: '校验通过'}
        },
        subShowControl(item){
            let conditionConfig = item.colHideConfig;
            if (!conditionConfig) {
                return true;
            }
            if(conditionConfig.isHide){
                return false
            }
            if(!conditionConfig.hideCondition){
                return true;
            }
            let {hideCondition} = conditionConfig;
            if (hideCondition.indexOf('return') === -1) {
                hideCondition = 'return ' + hideCondition;
            }
            let fn = new Function('row',hideCondition);
            return  !fn.call(this)
        },
        itemChildren(list,dataList){
            if(!dataList){
                dataList = []
            }
            list.forEach(res=>{
                if(res.children){
                    this.itemChildren(res.children,dataList)
                }else {
                    dataList.push(res)
                }
            })
            return dataList
        },
        //容器
        collapse(item) {
            let result = {success: true, msg: '校验通过'}
            let latent = this.showControl(item)//显示
            if (latent) {
                for (const res of item.children) {
                    let show = true
                    if(res.showConfig && res.showConfig.condition){
                        show = this.showConfig(res.showConfig)
                    }
                    if(show){
                        for (const res_ of res.list) {
                            let fn = this.forRules(res_);
                            if (fn && !fn.success) {
                                return fn
                            }
                        }
                    }
                }
            }
            return result
        },
        showConfig(res){
            let show = true
            let {condition} = res;
            if (condition && condition.indexOf('return') === -1) {
                condition = 'return ' + condition;
            }
            let fnCondition = new Function('row',condition);
            show = fnCondition.call(this,this.data)
            return show
        },
        //表格
        table(item) {
            let result = {success: true, msg: '校验通过'}
            let latent = this.showControl(item)//显示
            if (latent) {
                for (const res of item.trs) {
                    for (const res_tds of res.tds) {
                        for (const res_ of res_tds.children) {
                            let fn = this.forRules(res_);
                            if (fn && !fn.success) {
                                return fn
                            }
                        }
                    }
                }
            }
            return result
        },
        //tab容器
        tabs(item) {
            let result = {success: true, msg: '校验通过'}
            let latent = this.showControl(item)//显示
            if (latent) {
                for (const res of item.children) {
                    for (const res_ of res.list) {
                        let fn = this.forRules(res_);
                        if (fn && !fn.success) {
                            return fn
                        }
                    }
                }
            }
            return result
        },
        //一对一子表
        async oneTable(item,action) {
            let result = {success: true, msg: '校验通过'}
            let latent = this.showControl(item)//显示
            //一对一子表
            if(!latent){
                return result
            }
            for (let obj of item.children) {
                for (let objChildren of obj.children) {
                    for (let rulesItem of objChildren.rules) {
                        let name = this.$i18(item.name) + "[" + this.$i18(objChildren.name) + "]"
                        let fn = this.reqMsg(rulesItem, objChildren, this.data['sub__' + item.field][objChildren.field], name, this.permission.subTable[item.field].fields[objChildren.field], this.data['sub__' + item.field])
                        let value = this.data['sub__' + item.field][objChildren.field];
                        if (value && objChildren.options.uniqueValue) {
                            let isUnique = await this.checkUnique(objChildren, value, action,this.data['sub__' + item.field],objChildren.subTable);
                            if(!isUnique){
                                let language = uni.getStorageSync("language");
                                let name =objChildren.name;
                                return {success: false, msg: "子表【" + name[language] + "】唯一性校验不通过！"};
                            }
                        }
                        if (fn && !fn.success) {
                            return fn
                        }
                    }
                }
            }
        },
        forRules(res_) {
            if (res_.type == "oneTable") {
                let result = this.oneTable(res_);
                if (result && !result.success) {
                    return result
                }
            } else if (res_.type == 'subTable') {
                //总子表
                let result = this.subTableRules(res_);
                if (result && !result.success) {
                    return result
                }
            } else if (res_.rules) {
                for (let rulesItem of res_.rules) {
                    let fn = this.reqMsg(rulesItem, res_, this.data[res_.field], this.$i18(res_.name), this.permission.main[res_.field], this.data)
                    if (fn && !fn.success) {
                        return fn
                        break
                    }
                }
            }
        },
        //表单校验
        async formCheckRule(checkRequired, action) {
            this.checkRequired = checkRequired;
            for (let item of this.template) {
                let obj = {
                    subTable: this.subTableRules,
                    oneTable: this.oneTable,
                    grid: this.gridRules,
                    collapse: this.collapse,
                    table: this.table,
                    tabs: this.tabs,
                }
                if (Object.keys(obj).includes(item.type)) {//总子表
                    let result = await obj[item.type](item,action);
                    if (result && !result.success) {
                        return result
                    }
                } else if (this.permission.main[item.field] != 'none') {
                    //隐藏控件校验通过
                    if (item.rules) {
                        for (let rulesItem of item.rules) {
                            let fn = this.reqMsg(rulesItem, item, this.data[item.field], this.$i18(item.name), this.permission.main[item.field], this.data)
                            if (fn && !fn.success) {
                                return fn
                            }
                        }
                    }
                    //如果checkRequired：false则不校验必填
                    if (this.isCheckRequired()) {
                        if (this.permission.main[item.field] == 'required' && !this.data[item.field]) {
                            return {success: false, msg: this.$i18(item.name) + '必填'};
                        }
                    }
                }
                let value = this.data[item.field];
                if (value && item.options.uniqueValue && !item.subTable) {
                    let isUnique = await this.checkUnique(item, value, action);
                    if(!isUnique){
                        let language = uni.getStorageSync("language");
                        let name =item.name;
                        return {success: false, msg: "主表【" + name[language] + "】唯一性校验不通过！"};
                    }
                }
            }
            return {success: true, msg: '校验通过'};
        },
        chooseImage(params){
            uni.chooseImage(params);
        },
        showMessage(type,message){
            uni.showToast({
                title: message, duration: 2000, icon: 'none'
            });
        },
        showToast(title) {
            uni.showToast({
                title: title, duration: 2000, icon: 'none'
            });
        },
        getContainer(metadataOBJ) {
            let ary = [];
            //把容器中的组件循环出来
            let loopCtl = (config) => {
                loopControl(config, (item, type) => {
                    ary.push(item);
                })
            }
            loopCtl(metadataOBJ)
            return ary
        },
        setCtl(arr,list){
            for (let item of arr){
                if(!this.pcSelect[list.key]){
                    return
                }
                this.$set(list, item, this.pcSelect[list.key][item])
            }
        },
        getInit() {
            if(!this.template){
                return
            }
            this.template.forEach(item => {
                if (item.type === 'table') {
                    item.trs.forEach(res => {
                        res.tds.forEach(res_tds => {
                            this.getInitTr(res_tds)
                        })
                    })
                } else if (item.type === 'tabs') {
                    item.children.forEach(res => {
                        res.list.forEach(resList => {
                            if (resList.type === "subTable") {
                                let arr = ['children','control','rules'];
                                this.setCtl(arr,resList)
                            } else if (resList.type === "oneTable") {
                                let controlObj = {...resList.control}
                                let arr = ['control','field','rules'];
                                this.setCtl(arr,resList)
                                let controls = ['gutter','isResponsive'];
                                for(let item of controls){
                                    resList.control[item] = controlObj[item]
                                }
                                resList.children.forEach((resOneTable) => {
                                    this.getInitTr(resOneTable)
                                })
                            } else {
                                this.getInitTr(resList)
                            }
                        })
                    })
                } else if (item.type === "oneTable") {
                    let arr = ['control','field','rules'];
                    this.setCtl(arr,item)
                    item.children.forEach((res) => {
                        this.getInitTr(res)
                    })
                } else if (item.type === 'subTable') {
                    let arr = ['name','children','control','buttonConfig','rules','field','key','rowButtonConfig'];
                    this.setCtl(arr,item)
                } else if (item.type === "logo") {
                    return
                } else if (item.type === 'collapse') {
                    item.children.forEach(res => {
                        res.list.forEach(resList => {
                            this.getInitTr(resList)
                        })
                    })
                } else if (item.children) {
                    this.getInitTr(item)
                } else {
                    this.setForm(item)
                }
            })
        },
        getInitTr(itemChildren) {
            if (itemChildren.children) {
                itemChildren.children.forEach(itemChildren_ => {
                    if (itemChildren_.key && this.pcSelect[itemChildren_.key]) {
                        this.setForm(itemChildren_)
                    } else{
                        this.getInitTr(itemChildren_)
                    }
                })
            }else if(itemChildren.trs){
                itemChildren.trs.forEach(resTrs=>{
                    resTrs.tds.forEach(resTds=>{
                        resTds.children.forEach(itemChildren_ => {
                            if (itemChildren_.key && this.pcSelect[itemChildren_.key]) {
                                this.setForm(itemChildren_)
                            } else if (itemChildren_.children) {
                                this.getInitTr(itemChildren_)
                            }
                        })
                    })

                })
            }else if(itemChildren.list){
                itemChildren.list.forEach(resList=>{
                    this.setForm(resList)
                })
            } else {
                this.setForm(itemChildren)
            }
        },
        setForm(itemChildren_) {
            if (this.pcSelect[itemChildren_.key] && this.pcSelect[itemChildren_.key].subTable) {
                this.$set(itemChildren_, 'subTable', this.pcSelect[itemChildren_.key].subTable);
            }
            let arr = ['control', 'field', 'isForm', 'on', 'options', 'rules', 'style', 'type', 'name' ];
            this.setCtl(arr,itemChildren_)
        },
        setMobileSelect(value) {
            loopControl(value, (ctl, type) => {
                this.$set(this.pcSelect, ctl.key, ctl)
                if (type === 'oneTable') {
                    for (let col of ctl.children) {
                        if (col.children) {
                            loopControl(col.children, (c, t) => {
                                this.$set(this.pcSelect, c.key, c)
                            })
                        }
                    }
                } else if (type === 'subTable') {
                    let setSubKey = (sub) => {
                        for (let item of sub) {
                            if (item.children) {
                                setSubKey(item.children)
                            } else if (item.controlConfig && item.controlConfig.key) {
                                this.$set(this.pcSelect, item.controlConfig.key, item.controlConfig)
                            } else if (item.key) {
                                this.$set(this.pcSelect, item.key, item)
                            }
                        }
                    }
                    setSubKey(ctl.children)
                }
            })
        },
        /**
         * 打开列表。
         * @param alias     列表名称
         * @param params    传入参数，使用对象类型 参数键值数据例如 {user:"ray","Q_USER_S_EQ":"red"}
         * @param config    对象类型 {max:true,widthHeight:[data.width + 'px', data.height + 'px']}
         * @param destroy   回调函数 function(data){}
         */
        openList(alias, params, config, destroy) {
            let single = true;
            var parameter = "";
            if (params) {
                var aryParams = [];
                for (var key in params) {
                    if (key == "single") {
                        single = params[key];
                    }
                    aryParams.push(key + "=" + params[key]);
                }
                parameter = aryParams.join("&");
            }

            let conf = {
                data: {
                    alias: alias,
                    single: single,
                    params: parameter,
                },
                curVm: this,
            };
            Dialog.openDialog(conf, function (data) {
                if(data.action=="cancel"){
                    return
                }
                destroy(data.action, data.data);
            })
        },
        /**
         * 使用参数对象打开表单方案.
         * @param {Object} obj 参数对象
         */
        openFormSolution({
            //表单方案别名
            alias,
            //标题
            title,
            //传递表单数据
            params={},
            //回调方法
            destroy,
            //主键
            pk="",
            readOnly=false,
            closeOnSave=true,
            openMode={isMax:true,isShade:true,width:800,height:600}}) {
            this.openForm(alias,title,readOnly,pk,params,destroy);
        },
        /**
         * 打开表单方案
         * @param alias     表单方案名称
         * @param title     标题
         * @param readonly  是否只读
         * @param pk        主键
         * @param params    将数据映射到表单 {}
         * @param destroy   回调函数 function(action){
         *
         * }
         */
        openForm(alias, title, readonly, pk, params, destroy) {
            let paramsControl = {
                alias: alias,
                action: 'edit',
                pk: pk,
                relData: params,
                appId:Util.getAppId(this)
            }
            if (typeof readonly === "boolean") {
                if(readonly){
                    paramsControl.action = 'detail';
                }
            }else if(readonly){
                paramsControl.readonly = readonly
            }
            let conf = {
                data: {
                    isShowFormDialog: true,
                    paramsControl: paramsControl,
                },
                dialogOptions:{
                    title:title,
                    okText:''
                },
                curVm: this,
            };
            Dialog.openForm(conf, function (data) {
                if(destroy){
                    destroy(data.action, data.data);
                }
            })
        },
        getUtil() {
            return Util;
        },
        /*
        //get请求
         */
        get(url, params, head) {
            if(!head){
                head={
                    headers:{}
                }
            }
            let token = TokenUtil.getToken();
            if (token && !head.headers.authorization) {
                head.headers.authorization = 'Bearer ' + token;
            }
            let appId = Util.getAppId(this);
            if (appId && !head.headers.appid) {
                this.$set(head.headers, 'appid', appId)
            }
            if (params) {
                head = {...head, ...{'params': params}}
            }
            if(!url.includes('/api/')){
                url='/api'+url
            }
            return rxAjax.get(url, head);
        },
        /*
        //post请求
         */
        postJson(url, params, head) {
            if(!head){
                head={
                    headers:{}
                }
            }
            let token = TokenUtil.getToken();
            if (token && !head.headers.authorization) {
                head.headers.authorization = 'Bearer ' + token;
            }
            let appId = Util.getAppId(this);
            if (appId && !head.headers.appid) {
                this.$set(head.headers, 'appid', appId)
            }
            if(!url.includes('/api/')){
                url='/api'+url
            }
            return rxAjax.post(url, params, head);
        },
        getDialog(){
            return {...Dialog};
        },
        /*
          subTableName：子表的标识键
          row：子表的一行数据(item)
         */
        addRow(subTableName,row){
            if(this.data['sub__' + subTableName]){
                this.data['sub__' + subTableName].push(row)
            }
        },
        /**
         * 调用服务端脚本。
         */
        invokeScript(alias, params, callback) {
            FormApi.invoke(alias, params).then(res => {
                if(callback) {
                    callback(res);
                }
            })
        },
        /**
         * 调用服务端脚本
         */
        invokeScriptPromise(alias,params){
            return FormApi.invoke(alias,params);
        },
        /**
         * 调用自定义查询
         */
        invokeCustomQuery(alias,params,callback){
            FormApi.queryForJson(alias, {params: JSON.stringify(params)})
                .then(res=>{
                    if(res.success && callback) {
                        callback(res.data);
                    }
                })
        },
        /**
         * 调用自定义查询(同步)
         */
        invokeCustomQueryPromise(alias,params){
            return FormApi.queryForJson(alias,{params:JSON.stringify(params)});
        },
        /**
         * 调用第三方接口
         */
        invokeInterface(apiKey,params,callback){
            FormApi.executeInterfaceApi(apiKey,params).then(res=>{
                if(res.success && callback){
                    callback(res.data);
                }
            })
        },
        /**
         * 调用第三方接口(同步)
         */
        invokeInterfacePromise(apiKey,params){
            return FormApi.executeInterfaceApi(apiKey,params);
        },
        /**
         * 获取Tab控件
         * @param ref
         * @returns {*}
         */
        getComponent(ref) {
            let component;
            this.callbackComponent(this.$refs,
                function (refKey, refComponent) {
                    if (ref == refKey) {
                        component = refComponent;
                    }
                })
            if(component){
                return component.$refs.current;
            }
            return component;
        },
        callbackComponent(refs,callback){
            if(!refs){
                return;
            }
            for(let refKey of Object.keys(refs)){
                let refComponent = refs[refKey];
                if(refComponent) {
                    if (callback) {
                        if(refComponent instanceof Array && refComponent.length==1){
                            callback(refKey, refComponent[0]);
                            refComponent = refComponent[0];
                        }else{
                            callback(refKey, refComponent);
                        }
                    }
                    this.callbackComponent(refComponent.$refs, callback);
                }
            }
        },
        /**
         * 校验唯一性
         * @param item 当前控件
         * @param value 当前值
         * @param action
         * @returns {*}
         */
        checkUnique(item, value,action,data,alias) {
            let formJson = {
                "alias": alias || this.resForm.alias,
                "keyName": item.field,
                "keyValue": value,
                "formData": (data || this.data),
                "action": action
            }
            if(alias) {
                formJson.isSub = true;
            }
            return FormApi.checkUniqueValue(formJson);
        },
        /**
         * 执行规则引擎
         * @param liteFlowId
         * @param params
         * @returns {*}
         */
        executeLiteFlow(liteFlowId, params){
            return FormApi.executeLiteFlow(liteFlowId, params);
        },
        /**
         * @param obj
         * alias： 别名
         * params：参数
         * title:名称
         * config:{max:true,shade:true,width:200,height:200)}
         * callBack：回调函数
         */
        openCustomPage(alias,params,title,config,callBack){
            let paramsObj = {
                alias:alias,
                params:params,
                title:title,
                appId:Util.getAppId(this)
            }
            Dialog.openCustomPage(paramsObj,callBack)
            let res = {}
            if(callBack){
                callBack(res);
            }
        },
    },
    computed: {
        /*
        控件是否隐藏
         */
        curRequired() {
            return (item) => {
                if (item.rules) {
                    let required = false
                    item.rules.filter(res => {
                        if (res.condition) {
                            let condition = res.condition
                            if (!condition.includes('return')) {
                                condition = `return ${condition}`;
                            }
                            required = new Function(condition).call(this);
                        } else if (res.required) {
                            required = true
                        }
                    })
                    return required
                }
                return false;
            }
        },
        hasShowOrIf() {
            return (item) => {
                if (!item.control.conditionConfig) {
                    return 'if';
                }
                let {conditionConfig: {hideMethod}} = item.control;
                return hideMethod;
            }
        },
        condition() {
            return (item) => {
                //隐藏域
                if (item.type == "hidden") {
                    return false
                }
                let {conditionConfig} = item.control;
                if (!conditionConfig) {
                    return true
                }
                if (conditionConfig.condition) {
                    let {condition, isShow} = conditionConfig;
                    if (condition.indexOf('return') === -1) {
                        condition = 'return ' + condition;
                    }
                    let fn = new Function(condition);
                    return isShow ? !(fn.call(this)) : fn.call(this)
                }
                return conditionConfig.isShow;
            }
        },
    },
    mounted(){
        this.$nextTick(function () {
            //新增、编辑、明细时 执行自定义查询
            this.executeCustomQuery();
        })
    }
}
